﻿//-----------------------------------------------------------------------
// <copyright company="Microsoft Corporation">
//     Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//-----------------------------------------------------------------------

//#define WPF_4_0
#define WPF_3_5_SP1
//#define WPF_3_5
//#define WPF_3_0_SP2
//#define WPF_3_0_SP1
//#define WPF_3_0

#if WPF_3_5_SP1
#define WPF_3_5
#define WPF_3_0SP2
#endif

#if WPF_3_5
#define WPF_3_0SP1
#endif

#if WPF_3_0SP2
#define WPF_3_0SP1
#endif

#if WPF_3_0SP1
#define WPF_3_0
#endif

namespace Microsoft.DevDiv.Wpf.Samples
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Windows;
    using System.Windows.Media;
    using System.Windows.Media.Effects;
    using System.Diagnostics.CodeAnalysis;

    /// <Summary>
    /// LocalAdornerBase implementation with better XAML support
    /// </Summary>
    public class LocalAdorner : LocalAdornerBase
    {
        public static readonly DependencyProperty IsAdornmentVisibleProperty =
            DependencyProperty.Register(
            "IsAdornmentVisible",
            typeof(bool),
            typeof(LocalAdornerBase),
            new FrameworkPropertyMetadata(true, Handle_IsAdornmentVisibleChanged));

        public static readonly DependencyProperty AdornmentHostOffsetProperty =
            DependencyProperty.Register(
            "AdornmentHostOffset",
            typeof(Vector),
            typeof(LocalAdorner),
            new FrameworkPropertyMetadata(default(Vector), Handle_AdornmentHostOffsetChanged));

#if WPF_4_0
        public static readonly DependencyProperty AdornmentCacheModeProperty =
            DependencyProperty.Register(
            "AdornmentCacheMode",
            typeof(CacheMode),
            typeof(LocalAdorner),
            new FrameworkPropertyMetadata(default(CacheMode), Handle_AdornmentHostCacheModeChanged));
#endif

        public static readonly DependencyProperty AdornmentHostClipProperty =
            DependencyProperty.Register(
            "AdornmenHostClip",
            typeof(Geometry),
            typeof(LocalAdorner),
            new FrameworkPropertyMetadata(default(Geometry), Handle_AdornmentHostClipChanged));

#if WPF_4_0
        public static readonly DependencyProperty AdornmentHostEffectProperty =
            DependencyProperty.Register(
            "AdornmentHostEffect",
            typeof(Effect),
            typeof(LocalAdorner),
            new FrameworkPropertyMetadata(default(Effect), Handle_AdornmentHostEffectChanged));
#endif

        public static readonly DependencyProperty AdornmentHostOpacityProperty =
            DependencyProperty.Register(
            "AdornmentHostOpacity",
            typeof(double),
            typeof(LocalAdorner),
            new FrameworkPropertyMetadata(1.0, Handle_AdornmentHostOpacityChanged));

        public static readonly DependencyProperty AdornmentHostOpacityMaskProperty =
            DependencyProperty.Register(
            "AdornmentHostOpacityMask",
            typeof(Brush),
            typeof(LocalAdorner),
            new FrameworkPropertyMetadata(default(Brush), Handle_AdornmentHostOpacityMaskChanged));

        public static readonly DependencyProperty AdornmentHostTransformProperty =
            DependencyProperty.Register(
            "AdornmentHostTransform",
            typeof(Transform),
            typeof(LocalAdorner),
            new FrameworkPropertyMetadata(default(Transform), Handle_AdornmentHostTransformChanged));

        public static readonly DependencyProperty AdornmentHostXSnappingGuidelinesProperty =
            DependencyProperty.Register(
            "AdornmenHostXSnappingGuidelines",
            typeof(DoubleCollection),
            typeof(LocalAdorner),
            new FrameworkPropertyMetadata(default(DoubleCollection), Handle_AdornmentHostXSnappingGuidelinesChanged));

        public static readonly DependencyProperty AdornmentHostYSnappingGuidelinesProperty =
            DependencyProperty.Register(
            "AdornmentHostYSnappingGuidelines",
            typeof(DoubleCollection),
            typeof(LocalAdorner),
            new FrameworkPropertyMetadata(default(DoubleCollection), Handle_AdornmentHostYSnappingGuidelinesChanged));

        public event EventHandler<EventArgs> AdornedElementUpdated;

        /// <summary>
        /// Adornment element
        /// </summary>
        /// <CodeAnalysisSuppression>
        /// Keeping property name to make class XAML friendly
        /// </CodeAnalysisSuppression>
        [SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods")]
        public UIElement Adornment
        {
            get { return GetAdornment(); }
            set 
            { 
                SetAdornment(value);

                if (IsAdornmentVisible)
                {
                    ShowAdornment();
                }
                else
                {
                    HideAdornment();
                }
            }
        }

        /// <summary>
        /// Visibility of adornment
        /// </summary>
        public bool IsAdornmentVisible
        {
            get { return (bool)GetValue(IsAdornmentVisibleProperty); }
            protected set { SetValue(IsAdornmentVisibleProperty, value); }
        }

        /// <summary>
        /// Offset of adornment
        /// </summary>
        public Vector AdornmentHostOffset
        {
            get { return (Vector)GetValue(AdornmentHostOffsetProperty); }
            set { SetValue(AdornmentHostOffsetProperty, value); }
        }

#if WPF_4_0
        public CacheMode AdornmenHostCacheMode
        {
            get { return (CacheMode)GetValue(AdornmentHostCacheModeProperty); }
            set { SetValue(AdornmentHostCacheModeProperty, value); }
        }
#endif

        /// <summary>
        /// Cliping geometry of adornment
        /// </summary>
        public Geometry AdornmentHostClip
        {
            get { return (Geometry)GetValue(AdornmentHostClipProperty); }
            set { SetValue(AdornmentHostClipProperty, value); }
        }

#if WPF_4_0
        public Effect AdornmentHostEffect
        {
            get { return (Effect)GetValue(AdornmentHostEffectProperty); }
            set { SetValue(AdornmentHostEffectProperty, value); }
        }
#endif

        /// <summary>
        /// Opacity of adornment
        /// </summary>
        public double AdornmentHostOpacity
        {
            get { return (double)GetValue(AdornmentHostOpacityProperty); }
            set { SetValue(AdornmentHostOpacityProperty, value); }
        }

        /// <summary>
        /// Opacity mask of adornment
        /// </summary>
        public Brush AdornmentOpacityMask
        {
            get { return (Brush)GetValue(AdornmentHostOpacityMaskProperty); }
            set { SetValue(AdornmentHostOpacityMaskProperty, value); }
        }

        /// <summary>
        /// Transform of adornment
        /// </summary>
        public Transform AdornmentTransform
        {
            get { return (Transform)GetValue(AdornmentHostTransformProperty); }
            set { SetValue(AdornmentHostTransformProperty, value); }
        }

        /// <summary>
        /// Snapping guidelines of adornment
        /// </summary>
        /// <CodeAnalysisSupression>Setter exists to expose underlying functionality on ContainerVisual in a XAML friendly way</CodeAnalysisSupression>
        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public DoubleCollection AdornmentHostXSnappingGuidelines
        {
            get { return (DoubleCollection)GetValue(AdornmentHostXSnappingGuidelinesProperty); }
            set { SetValue(AdornmentHostXSnappingGuidelinesProperty, value); }
        }

        /// <summary>
        /// Snapping guidelines of adornment
        /// </summary>
        /// <CodeAnalysisSupression>Setter exists to expose underlying functionality on ContainerVisual in a XAML friendly way</CodeAnalysisSupression>
        [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
        public DoubleCollection AdornmentHostYSnappingGuidelines
        {
            get { return (DoubleCollection)GetValue(AdornmentHostYSnappingGuidelinesProperty); }
            set { SetValue(AdornmentHostYSnappingGuidelinesProperty, value); }
        }

        /// <summary>
        /// Called when adorned element is updated and the adornments state may need to referesh its state
        /// </summary>
        /// <param name="e">Event arguments</param>
        protected override void OnAdornedElementUpdated(EventArgs e)
        {
            EventHandler<EventArgs> h = AdornedElementUpdated;
            if (h != null)
            {
                h(this, EventArgs.Empty);
            } 	    
        }

        private static void Handle_IsAdornmentVisibleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((LocalAdorner)sender).OnIsAdornmentVisibleChanged((bool)e.OldValue, (bool)e.NewValue);
        }

        private void OnIsAdornmentVisibleChanged(bool oldIsVisible, bool newIsVisible)
        {
            if (oldIsVisible != newIsVisible)
            {
                if (newIsVisible)
                {
                    ShowAdornment();
                }
                else
                {
                    HideAdornment();
                }
            }
        }

        private static void Handle_AdornmentHostOffsetChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((LocalAdorner)sender).SetAdornmentHostOffset((Vector)e.NewValue);
        }

#if WPF_4_0

        private static void Handle_AdornmentHostCacheModeChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((LocalAdorner)sender).SetAdornmentHostCacheMode((CacheMode)e.NewValue);
        }
#endif

        private static void Handle_AdornmentHostClipChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((LocalAdorner)sender).SetAdornmentHostClip((Geometry)e.NewValue);
        }

#if WPF_4_0
        private static void Handle_AdornmentHostEffectChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((LocalAdorner)sender).SetAdornmentHostEffect((Effect)e.NewValue);
        }
#endif

        private static void Handle_AdornmentHostOpacityChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((LocalAdorner)sender).SetAdornmentHostOpacity((double)e.NewValue);
        }

        private static void Handle_AdornmentHostOpacityMaskChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((LocalAdorner)sender).SetAdornmentHostOpacityMask((Brush)e.NewValue);
        }

        private static void Handle_AdornmentHostTransformChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((LocalAdorner)sender).SetAdornmentHostTransform((Transform)e.NewValue);
        }

        private static void Handle_AdornmentHostXSnappingGuidelinesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((LocalAdorner)sender).SetAdornmentHostXSnappingGuidelines((DoubleCollection)e.NewValue);
        }

        private static void Handle_AdornmentHostYSnappingGuidelinesChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            ((LocalAdorner)sender).SetAdornmentHostYSnappingGuidelines((DoubleCollection)e.NewValue);
        }
    }
}
